"""WMS3D系统主应用入口点。

该模块是WMS3D系统的主应用文件，负责：
1. 初始化系统组件
2. 挂载子应用（传感器网关、WMS核心）
3. 管理应用生命周期
4. 提供系统级端点（根路径、健康检查）
5. 启动服务器

系统采用微服务架构，将不同功能模块作为独立的子应用挂载。
"""

import logging
from contextlib import asynccontextmanager

import uvicorn
from fastapi import FastAPI, Request
from fastapi.responses import Response
import json

# from src.wms3d.api.trajectory_app import trajectories_app
from src.wms3d.api.wms_core import wms_app
from src.wms3d.core.config import settings
from src.wms3d.core.telemetry import instrument_fastapi, setup_telemetry

# 配置日志
logging.basicConfig(
    level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)

# 初始化遥测
setup_telemetry()


@asynccontextmanager
async def lifespan(app: FastAPI) -> None:
    """应用生命周期管理器。

    在应用启动时初始化数据库表，在应用关闭时执行清理工作。

    Args:
        app (FastAPI): FastAPI应用实例
    """
    logger.info("正在启动WMS3D系统...")

    # 初始化数据库表
    try:
        from src.wms3d.infrastructure.database import create_tables

        await create_tables()
        logger.info("数据库表初始化成功")
    except Exception as e:
        logger.error(f"初始化数据库表失败: {e}")

    yield

    logger.info("正在关闭WMS3D系统...")


# 创建主FastAPI应用
app = FastAPI(
    title="WMS3D系统", description="3D实时仓库管理系统", version="1.0.0", lifespan=lifespan
)

# 仪器化FastAPI应用
instrument_fastapi(app)


# 添加请求/响应追踪中间件
@app.middleware("http")
async def trace_request_response_middleware(request: Request, call_next):
    """中间件用于追踪HTTP请求和响应"""
    from opentelemetry import trace
    
    # 获取当前span
    current_span = trace.get_current_span()
    
    # 只对WMS核心API添加详细追踪
    if request.url.path.startswith("/wms/"):
        # 添加请求信息到追踪中
        current_span.set_attribute("http.method", request.method)
        current_span.set_attribute("http.url", str(request.url))
        current_span.set_attribute("http.user_agent", request.headers.get("user-agent", ""))
        
        # 只在调试模式下捕获请求体（注意：这可能会影响性能）
        if settings.wms.debug:
            try:
                # 注意：这种方法会消耗请求体，可能影响后续处理
                # 仅在调试模式下启用，并且只处理小的请求体
                body = await request.body()
                if body and len(body) < 1024:  # 限制大小以避免性能问题
                    body_str = body.decode("utf-8")
                    # 限制长度并添加到追踪中
                    current_span.set_attribute("http.request.body.preview", body_str[:200])
            except Exception:
                pass  # 忽略读取错误
    
    # 处理请求
    response = await call_next(request)
    
    # 添加响应信息到追踪中
    if request.url.path.startswith("/wms/"):
        try:
            # 添加响应状态码
            current_span.set_attribute("http.response.status_code", response.status_code)
            
            # 只在调试模式下捕获响应体（注意：这可能会影响性能）
            if settings.wms.debug:
                try:
                    # 尝试从响应头获取内容长度
                    content_length = response.headers.get("content-length")
                    if content_length and int(content_length) < 1024:
                        # 对于小的响应体，可以考虑记录预览
                        # 注意：直接访问response.body可能不总是有效
                        pass
                except Exception:
                    pass  # 忽略读取错误
        except Exception:
            pass  # 忽略读取错误
    
    return response


# 挂载子应用
app.mount("/wms", wms_app, name="wms-core")  # WMS核心API


@app.get("/")
async def root() -> dict:
    """根路径端点。

    提供系统基本信息和可用端点列表。

    Returns:
        dict: 系统信息和端点列表
    """
    return {
        "message": "WMS3D系统 - 3D实时仓库管理系统",
        "version": "1.0.0",
        "endpoints": {
            "wms_core": "/wms",
            "health": "/health",
        },
    }


@app.get("/health")
async def health_check() -> dict:
    """系统健康检查端点。

    检查系统各服务组件的运行状态。

    Returns:
        dict: 健康检查结果
    """
    return {
        "status": "healthy",
        "services": {
            "sensor_gateway": "mounted",
            "wms_core": "mounted",
        },
        "timestamp": "2024-01-01T00:00:00Z",
    }


def run_wms_server() -> None:
    """运行WMS核心服务器。

    使用uvicorn启动主应用服务器。
    """
    uvicorn.run(
        "main:app",
        host=settings.wms.host,
        port=settings.wms.port,
        reload=settings.wms.debug,
        log_level="info",
    )



if __name__ == "__main__":
    run_wms_server()
